(library (handlers)
  (export not-found-404-handler
          debug-handler
          hello-world-handler
          minimal-static-asset-handler)
  (import
    (except (rnrs base) let-values)
    (only (guile) lambda* λ error when display sleep)

    ;; Guile modules
    ;; alist->hash-table
    (prefix (ice-9 hash-table) ice9-hash-table:)
    ;; Guile exception handling
    (ice-9 exceptions)
    (ice-9 session)
    ;; for bytevector operations
    (ice-9 binary-ports)

    ;; SRFIs
    ;; hash tables
    (prefix (srfi srfi-69) srfi-69:)
    ;; receive form
    (prefix (srfi srfi-8) srfi-8:)
    ;; let-values
    (prefix (srfi srfi-11) srfi-11:)
    ;; list utils
    (prefix (srfi srfi-1) srfi-1:)

    ;; web server, concurrent
    (fibers web server)
    ;; standard web library
    (web request)
    (web response)
    (web uri)
    (sxml simple)
    ;; custom modules
    (path-handling)
    (web-path-handling)
    (file-reader)
    (mime-types)
    (prefix (logging) log:)
    (templates)
    (response-utils)))


;; Next we define some handlers, which take care of handling
;; specific routes.

(define not-found-404-handler
  (λ (request body)
    "Answer with a 404 HTTP status code."
    (values (build-response #:code 404)
            (string-append "requested resource not found: "
                           (uri->string (request-uri request))))))


(define debug-handler
  (lambda (request body)
    "The debug-handler will put all request headers into the
rendered HTML, so that we can see them on the page."
    (log:debug "responding using debug handler")
    (respond
     ;; Inside respond the SXML will be put into a template,
     ;; so there is no need to add html or body tags.
     (debug-table-template request body))))


(define hello-world-handler
  (lambda (request request-body)
    "A handler for a route."
    ;; A handler must return 2 values: The header and body
    ;; of the response.
    (values
     ;; Return the headers as first value (the bare
     ;; minimum).
     '((content-type . (text/plain)))
     ;; Then the response body. This is an example for
     ;; returning a string as second value, instead of a
     ;; procedure, which takes an output port.
     "Hello World!")))


(define minimal-static-asset-handler
  (λ (request body)
    (log:debug "responding using minimal-static-asset-handler")
    (let ([status 200]
          [content-type-params '((charset . "utf-8"))]
          [content-type 'text/css]
          [extra-headers '()])
      (values (build-response #:code status
                            ;; headers are an alist
                            #:headers
                            `((content-type . (,content-type ,@content-type-params))
                              ,@extra-headers))
              "body {margin: none}"))))
